﻿using Miao;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace Miao.ML
{
	internal class Analyzer
	{
		private const int defaultStringTextLength = 128;

		private readonly StringBuilder stringBuilder = new StringBuilder(128);
		//索引性质的Object字典，根本不需要给每个类型的对象序号，而给每个对象序号就足够了。
		private readonly Dictionary<object, int> objectDictionary = new Dictionary<object, int>();
		//基类属性解析
		private readonly Dictionary<Type, Func<object, string>> baseAnalyticalDictionary = new Dictionary<Type, Func<object, string>>(7);

		private readonly Dictionary<string, Func<object, string>> customAnalyticalDictionary = new Dictionary<string, Func<object, string>>();

		private int currentObjectID;

		public Analyzer()
		{
			baseAnalyticalDictionary.Add(TypeCache.intType, IntData.ToString);
			baseAnalyticalDictionary.Add(TypeCache.boolType, BoolData.ToString);
			baseAnalyticalDictionary.Add(TypeCache.longType, LongData.ToString);
			baseAnalyticalDictionary.Add(TypeCache.floatType, FloatData.ToString);
			baseAnalyticalDictionary.Add(TypeCache.doubleType, DoubleData.ToString);
			baseAnalyticalDictionary.Add(TypeCache.stringType, StringData.ToString);
		}
		/// <summary>
		/// 自定义序列化用
		/// </summary>
		/// <param name="type"></param>
		/// <param name="function"></param>
		/// <exception cref="Exception"></exception>
		public void AddCustomAnalyticalFunction(Type type, Func<object, string> function)
		{
			if (customAnalyticalDictionary.TryAdd(type.FullName, function))
			{
				return;
			}
			throw new Exception("WinMLSerializer.AddCustomAnalyticalFunction: 解析类型 " + type.FullName + " 已有一个解析方法, 不能重复添加!");
		}

		public string AnalyzeObject(object obj)
		{
			currentObjectID = 0;
			stringBuilder.Length = 0;
			objectDictionary.Clear();
			RecursiveAnalyze(obj, obj.GetType());
			return stringBuilder.ToString();
		}
		//递归解析
		private void RecursiveAnalyze(object obj, Type objType)
		{
			Func<object, string> fucDict;
			if (obj != null && objectDictionary.TryGetValue(obj, out var value))//已存在对象取空和引用
			{
				stringBuilder.Append(value);
				stringBuilder.Append('*');
			}
			else if (baseAnalyticalDictionary.TryGetValue(objType, out fucDict))//这段就是存基础属性的ToString转换
			{
				stringBuilder.Append(fucDict(obj));
			}
			else if (objType.IsEnum)
			{
				AnalyzeEnum(obj, objType);
			}
			else if (customAnalyticalDictionary.ContainsKey(objType.FullName))
			{
				AnalyzeCustomObject(obj, objType);
			}
			else if (objType.IsValueType)//这里处理自定义Value的处理像struct
			{
				if (objType.IsGenericType)//泛型值对象
				{
					AnalyzeGenericValueObject(obj, objType);
				}
				else
				{
					AnalyzeValueObject(obj, objType);
				}
			}
			else if (objType.IsGenericType)//泛型类型，list也是泛型类型
			{
				Type genericTypeDefinition = objType.GetGenericTypeDefinition();
				if (genericTypeDefinition == TypeCache.listOpenType)//单独列表处理
				{
					AnalyzeList(obj, objType, isCustomList: false);
					return;
				}
				if (genericTypeDefinition == TypeCache.dictionaryOpenType)
				{
					AnalyzeDictionary(obj, objType, isCustomDictionary: false);
					return;
				}
				bool flag = false;
				bool flag2 = false;
				bool flag3 = false;
				bool flag4 = false;
				Type[] interfaces = objType.GetInterfaces();
				foreach (Type type in interfaces)
				{
					flag |= type == TypeCache.ilistOpenType;
					flag2 |= type == TypeCache.idictionaryOpenType;
					if (type.IsGenericType)
					{
						genericTypeDefinition = type.GetGenericTypeDefinition();
						flag3 |= genericTypeDefinition == TypeCache.ilistGenericOpenType;
						flag4 |= genericTypeDefinition == TypeCache.idictionaryGenericOpenType;
					}
				}
				if (flag && flag3)
				{
					AnalyzeList(obj, objType, isCustomList: true);
				}
				else if (flag2 && flag4)
				{
					AnalyzeDictionary(obj, objType, isCustomDictionary: true);
				}
				else
				{
					AnalyzeGenericReferenceObject(obj, objType);
				}
			}
			else
			{
				AnalyzeReferenceObject(obj, objType);
			}
		}

		private void WriteGenericType(Type objType)
		{
			stringBuilder.Append(objType.GetGenericTypeDefinition().FullName);
			WriteGenericTypeWithoutTypeName(objType);
		}
		//直接把泛型标识出来
		private void WriteGenericTypeWithoutTypeName(Type objType)
		{
			stringBuilder.Append('<');
			Type[] genericArguments = objType.GetGenericArguments();//拥有标识的泛型数量
			foreach (Type type in genericArguments)
			{
				if (!type.IsGenericType)
				{
					stringBuilder.Append(type.FullName);
				}
				else
				{
					WriteGenericType(type);
				}
				stringBuilder.Append(',');
			}
			stringBuilder.Length--;
			stringBuilder.Append('>');
		}

		private void AnalyzeEnum(object obj, Type objType)
		{
			stringBuilder.Append(objType.FullName);
			stringBuilder.Append('&');
			stringBuilder.Append(obj.ToString());
		}

		private void AnalyzeList(object obj, Type objType, bool isCustomList)
		{
			if (isCustomList)
			{
				WriteGenericType(objType);
			}
			else
			{
				WriteGenericTypeWithoutTypeName(objType);
			}
			stringBuilder.Append('&');
			if (obj == null)
			{
				stringBuilder.Append("null");
				stringBuilder.Append('[');
				stringBuilder.Append(']');
				return;
			}
			IList list = obj as IList;
			objectDictionary.Add(obj, currentObjectID);
			stringBuilder.Append(currentObjectID++);
			stringBuilder.Append('[');
			if (list.Count > 0)
			{
				foreach (object item in list)
				{
					if (item == null)
					{
						stringBuilder.Append("null");
					}
					else
					{
						RecursiveAnalyze(item, item.GetType());
					}
					stringBuilder.Append(',');
				}
				stringBuilder.Length--;
			}
			stringBuilder.Append(']');
		}

		private void RecursiveAnalzeDelegagteList(MulticastDelegate saveDelegate)
		{
				var invocationList = saveDelegate.GetInvocationList();
				for(int i=0;i< invocationList.Length;i++)
				{
				AnalyzeDelegagte(invocationList[i] as MulticastDelegate);
                }
			    stringBuilder.Length--;//消除后一位逗号
            
		}

		private void AnalyzeDelegagte(MulticastDelegate action)
		{
            var methodInfo = action.Method;
            
            // 检测匿名函数
            if (IsAnonymousFunction(methodInfo))
            {
                throw new NotSupportedException($"不支持序列化匿名函数: {methodInfo.Name}。请使用命名方法替代。");
            }
            
            if (methodInfo.IsStatic)
            {
                stringBuilder.Append("null");
                stringBuilder.Append("|");
                stringBuilder.Append(action.Method.Name);
            }
            else
            {
                RecursiveAnalyze(action.Target, action.Target.GetType());//只可能是引用
                stringBuilder.Append("|");
                stringBuilder.Append(action.Method.Name);
            }
            stringBuilder.Append(',');
        }
        
        /// <summary>
        /// 检测方法是否为匿名函数（lambda表达式）
        /// </summary>
        private bool IsAnonymousFunction(MethodInfo methodInfo)
        {
            string methodName = methodInfo.Name;
            return methodName.Contains("<>") || 
                   methodName.Contains("b__") || 
                   methodName.StartsWith("<") || 
                   methodName.Contains("DisplayClass");
        }

        /// <summary>
        /// 实际的对象解析
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="objType"></param>
        private void AnalyzeObject(object obj, Type objType)
		{
			stringBuilder.Append('{');
			FieldInfo[] fields = objType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			int num = 0;
			foreach (FieldInfo fieldInfo in fields)
			{
				if ((fieldInfo.IsPrivate && fieldInfo.GetCustomAttribute<WinMLSerializableAttribute>() == null) || fieldInfo.GetCustomAttribute<WinMLNonSerializableAttribute>() != null)
				{
					continue;
				}
				Type fieldType = fieldInfo.FieldType;//Action就是multicastDelegateType
                //Test
				if (fieldType.BaseType == TypeCache.multicastDelegateType)//回调委托
				{


                    MulticastDelegate action =  fieldInfo.GetValue(obj) as MulticastDelegate;//静态函数是没有Target的
					
					if (action != null)
					{
						
						
						
							//撰写字段名称
							stringBuilder.Append(fieldInfo.Name);//方法名称
							stringBuilder.Append('=');//方法不需要类型，
                        if (fieldType.IsGenericType)
                        {
							WriteGenericType(fieldType);

                        }
						else
						{
                            stringBuilder.Append(fieldType);
                        }
							//stringBuilder.Append("&-1");
							stringBuilder.Append('【');
							RecursiveAnalzeDelegagteList(action);
							stringBuilder.Append('】');
							stringBuilder.Append(',');
						
                    }

                    continue;
				}
				num++;
				stringBuilder.Append(fieldInfo.Name);
				stringBuilder.Append('=');
				object value = fieldInfo.GetValue(obj);
				if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == TypeCache.nullableOpenType)//一些泛型判空处理
				{
					stringBuilder.Append('?');
					if (value == null)
					{
						stringBuilder.Append("null");
					}
					else
					{
						RecursiveAnalyze(value, value.GetType());
					}
				}
				else
				{
					RecursiveAnalyze(value, (value == null) ? fieldType : value.GetType());
				}
				stringBuilder.Append(',');
			}
			PropertyInfo[] properties = objType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
			int num2 = 0;
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (propertyInfo.GetCustomAttribute<WinMLSerializableAttribute>() != null && !(propertyInfo.SetMethod == null))
				{
					Type propertyType = propertyInfo.PropertyType;
					if (!(propertyType.BaseType == TypeCache.multicastDelegateType))
					{
						num2++;
						stringBuilder.Append(propertyInfo.Name);
						stringBuilder.Append('=');
						object value2 = propertyInfo.GetValue(obj);
						RecursiveAnalyze(value2, (value2 == null) ? propertyType : value2.GetType());
						stringBuilder.Append(',');
					}
				}
			}
			if (num + num2 > 0)
			{
				stringBuilder.Length--;
			}
			stringBuilder.Append('}');
		}

		private void AnalyzeDictionary(object obj, Type objType, bool isCustomDictionary)
		{
			if (isCustomDictionary)
			{
				WriteGenericType(objType);
			}
			else
			{
				WriteGenericTypeWithoutTypeName(objType);
			}
			stringBuilder.Append('&');
			if (obj == null)
			{
				stringBuilder.Append("null");
				stringBuilder.Append('(');
				stringBuilder.Append(')');
				return;
			}
			IDictionary dictionary = obj as IDictionary;
			objectDictionary.Add(obj, currentObjectID);
			stringBuilder.Append(currentObjectID++);
			stringBuilder.Append('(');
			if (dictionary.Count > 0)
			{
				foreach (DictionaryEntry item in dictionary)
				{
					object key = item.Key;
					RecursiveAnalyze(key, key.GetType());
					stringBuilder.Append(':');
					object value = item.Value;
					if (value == null)
					{
						stringBuilder.Append("null");
					}
					else
					{
						RecursiveAnalyze(value, value.GetType());
					}
					stringBuilder.Append(',');
				}
				stringBuilder.Length--;
			}
			stringBuilder.Append(')');
		}
		/// <summary>
		/// 自定义对象
		/// </summary>
		/// <param name="obj"></param>
		/// <param name="objType"></param>
		private void AnalyzeCustomObject(object obj, Type objType)
		{
			stringBuilder.Append(objType.FullName);
			stringBuilder.Append('&');
			if (obj == null)
			{
				stringBuilder.Append("null");
				stringBuilder.Append(Keyword.caret);
				stringBuilder.Append(Keyword.caret);
				return;
			}
			if (objType.IsValueType)//-1就是标识中结构体的意思
			{
				stringBuilder.Append(-1);
			}
			else
			{
				objectDictionary.Add(obj, currentObjectID);
				stringBuilder.Append(currentObjectID++);
			}
			stringBuilder.Append(Keyword.caret);
			stringBuilder.Append(customAnalyticalDictionary[objType.FullName](obj));
			stringBuilder.Append(Keyword.caret);
		}

		private void AnalyzeValueObject(object obj, Type objType)
		{
			stringBuilder.Append(objType.FullName);
			AnalyzeValueObjectCore(obj, objType);
		}

		private void AnalyzeReferenceObject(object obj, Type objType)
		{
			stringBuilder.Append(objType.FullName);//引用类型，写名称
			AnalyzeReferenceObjectCore(obj, objType);
		}
		//泛型值对象
		private void AnalyzeGenericValueObject(object obj, Type objType)
		{
			WriteGenericType(objType);
			AnalyzeValueObjectCore(obj, objType);
		}

		private void AnalyzeGenericReferenceObject(object obj, Type objType)
		{
			WriteGenericType(objType);
			AnalyzeReferenceObjectCore(obj, objType);
		}
		//这里引用写-1就是结构体
		private void AnalyzeValueObjectCore(object obj, Type objType)
		{
			stringBuilder.Append('&');
			stringBuilder.Append(-1);
			AnalyzeObject(obj, objType);
		}

		private void AnalyzeReferenceObjectCore(object obj, Type objType)
		{
			stringBuilder.Append('&');//引用标识符&
			if (obj == null)
			{
				stringBuilder.Append("null");
				stringBuilder.Append('{');
				stringBuilder.Append('}');
			}
			else
			{
				objectDictionary.Add(obj, currentObjectID);
				stringBuilder.Append(currentObjectID++);//记下1啊对象和几下对象ID
				AnalyzeObject(obj, objType);
			}
		}
	}
}
